JDK 24 was released on March 18, 2025! As with my previous blogs, I have compiled a list of what I think are the most interesting and useful security enhancements in this release. I have also grouped them into appropriate categories (crypto, PKI, etc) which should make it easier to find out what has changed in each specific area. The JDK 24 release notes also contain further details on these and other enhancements.
This is a significant release for Java Security as it contains two new core quantum-resistant cryptographic algorithms, ML-KEM for key encapsulation, and ML-DSA for digital signatures. It also includes a new Preview API for Key Derivation Functions, which will be an important building block for subsequent post-quantum cryptography work. This release also permanently disables the Security Manager.
In addition, JDK 24 includes one other important feature that improves security but is not part of the security libraries area:
-
JEP 498: Warn upon Use of Memory-Access Methods in sun.misc.Unsafe
A warning is now issued at run time on the first use of the memory-access methods in
sun.misc.Unsafe
. These methods were deprecated for removal in JDK 23 in JEP 471.
Table of Contents
Crypto
-
JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
The
SunJCE
provider now supports the quantum-resistant ML-KEM key encapsulation mechanism. This mechanism is specified in FIPS 203, and is based on lattices. NewKeyPairGenerator
,KeyFactory
, andKEM
implementations for ML-KEM have been added. Three parameter sets in increasing strength are supported: ML-KEM-512, ML-KEM-768, and ML-KEM-1024.Here is an example which uses ML-KEM to establish a shared secret key between two parties, a sender and a receiver:
// The receiver generates an ML-KEM-768 key pair KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-KEM"); kpg.initialize(NamedParameterSpec.ML_KEM_768); KeyPair kp = kpg.genKeyPair(); // The sender obtains the receiver's public key from // an X.509 certificate (this part is not shown) // The sender generates a key encapsulation message and secret key // from the receiver’s public key KEM kem = KEM.getInstance("ML-KEM"); KEM.Encapsulator enc = kem.newEncapsulator(receiverCert.getPublicKey()); KEM.Encapsulated encap = enc.encapsulate(); SecretKey skey = encap.key(); byte[] msg = encap.encapsulation(); // send this to the receiver // The sender then sends the encapsulated message to the receiver // (this part is not shown) // The receiver decapsulates the key encapsulation message with its // private key to obtain the secret key byte[] msg = …; // received from sender KEM kem = KEM.getInstance("ML-KEM"); KEM.Decapsulator dec = kem.newDecapsulator(kp.getPrivateKey()); SecretKey skey = dec.decapsulate(msg);
The
keytool
utility also supports generating ML-KEM key pairs. Here is an example of generating an ML-KEM key pair and certificate:
$ keytool -keystore ks -storepass changeit \ -genkeypair -alias ec -keyalg EC \ -dname CN=EC -ext bc Generating 384-bit EC (secp384r1) key pair and self-signed certificate (SHA384withECDSA) with a validity of 90 days for: CN=EC $ keytool -keystore ks -storepass changeit \ -genkeypair -alias mlkem -keyalg ML-KEM \ -groupname ML-KEM-768 -dname CN=ML-KEM \ -signer ec Generating ML-KEM-768 key pair and a certificate (SHA384withECDSA) issued by <ec> with a validity of 90 days for: CN=ML-KEM
Note that in order to create the certificate, we need a different key to sign the certificate because ML-KEM itself is not a signature algorithm. The first command creates an EC key pair and self-signed certificate and the second command creates an ML-KEM-768 key pair and a certificate signed by the EC key.
JEP: 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
-
JEP 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
The
SUN
provider now supports the quantum-resistant ML-DSA signature algorithm. This algorithm is specified in FIPS 204, and is based on lattices. NewKeyPairGenerator
,KeyFactory
, andSignature
implementations for ML-DSA have been added. Three parameter sets in increasing strength are supported: ML-DSA-44, ML-DSA-65, and ML-DSA-87.Using ML-DSA in your applications is very similar to other signature algorithms. Here is an example which uses ML-DSA to sign and verify a message:
// The signer generates an ML-DSA-65 key pair KeyPairGenerator kpg = KeyPairGenerator.getInstance("ML-DSA"); kpg.initialize(NamedParameterSpec.ML_DSA_65); KeyPair kp = kpg.genKeyPair(); // The signer signs a message using its private key Signature sig = Signature.getInstance("ML-DSA"); sig.initSign(kp.getPrivate()); sig.update(message); byte[] signature = sig.sign(); // The signer then sends the signed message to the verifier // (this part is not shown) // The verifier verifies the message using the signer’s public key // (which in this case is in an X.509 certificate) Signature sig = Signature.getInstance("ML-DSA"); sig.initVerify(signerCert); sig.update(message); assert sig.verify(signature);
The
keytool
utility also supports generating ML-DSA key pairs. Here is an example of generating an ML-DSA key pair and certificate:
$ keytool -keystore ks -storepass changeit \ -genkeypair -alias mldsa -keyalg ML-DSA \ -groupname ML-DSA-65 -dname CN=ML-DSA Generating ML-DSA-65 key pair and self-signed certificate (ML-DSA-65) with a validity of 90 days for: CN=ML-DSA
This command creates an ML-DSA-65 key pair and a self-signed certificate.
JEP: 497: Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm
-
JEP 478: Key Derivation Function API (Preview)
A new preview API for deriving keys from key material has been introduced in this release and is more fully described in JEP 478. It includes an implementation of the HMAC-based Extract-and-Expand Key Derivation Function (HKDF), which is defined in RFC 5869.
KDF will be a very valuable API for several future enhancements that depend on key derivation. These include PQC mechanisms such as Hybrid Key Exchange in TLS 1.3 (IETF Draft) and Hybrid Public Key Encryption (RFC 9180). The API is also designed to be used for strong and modern password-based algorithms such as Argon2 (RFC 9106).
The main new class is
javax.crypto.KDF
. The JEP gives an example of using the HKDF-SHA256 algorithm to derive a 32 byte AES key:
// Create a KDF object for the specified algorithm KDF hkdf = KDF.getInstance("HKDF-SHA256"); // Create an ExtractExpand parameter specification AlgorithmParameterSpec params = HKDFParameterSpec.ofExtract() .addIKM(initialKeyMaterial) .addSalt(salt).thenExpand(info, 32); // Derive a 32-byte AES key SecretKey key = hkdf.deriveKey("AES", params);
-
Standard Hash and MGF Algorithm Names Defined for RSASSA-PSS Signatures
A new PSSParameterSpec section has been added to the Java Security Standard Algorithm Names Specification listing the standard hash and MGF (Message Generation Function) algorithms that can be specified when instantiating a
java.security.spec.PSSParameterSpec
object.Issue: JDK-8248981
-
SHA3 Performance Improved
The performance of the SHA3
MessageDigest
implementations has improved by 6% to 27%, depending on the platform and the length of the message digest. This performance improvement applies to the SHA3-224, SHA3-256, SHA3-384, and SHA3-512 algorithms. An additional 30-40% can be experienced on AVX-512 capable platforms due to new intrinsic implementations on that platform.Issue: JDK-8333867
-
PKCS#11 Support for AES CTS (Ciphertext Stealing) Mode
The
SunPKCS11
provider has been enhanced to support AES Ciphertext Stealing mode, if the configured PKCS#11 token supports it. The “AES/CTS/NoPadding”, “AES_128/CTS/NoPadding”, “AES_192/CTS/NoPadding”, and “AES_256/CTS/NoPadding”Cipher
algorithms are supported.The PKCS#11
cipherTextStealingVariant
attribute should be set to the CTS variant used by the PKCS#11 implementation. These correspond to the 3 variants defined by NIST SP 800-38A:CS1
,CS2
, andCS3
. If NSS is used as the PKCS#11 implementation, it automatically sets it toCS1
. If this attribute is not set, the CTS modes are disabled by default.Issue: JDK-8330842
PKI
-
New Root CA Certificates
Several new root CA certificates have been added to the
cacerts
keystore:- Two SSL.com root CA certificates
- SSL.com TLS ECC Root CA 2022 has the following distinguished name:
CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US
- SSL.com TLS RSA Root CA 2022 has the following distinguished name:
CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US
These root certificates have also been added to the
cacerts
keystore in Oracle’s JDK 23.0.1, 21.0.5, 17.0.13, 11.0.25, and 8u431 releases.Issue: JDK-8341057
- SSL.com TLS ECC Root CA 2022 has the following distinguished name:
- Two SSL.com root CA certificates
TLS
-
New Wildcard Mechanism for Disabling TLS Cipher Suites
The
jdk.tls.disabledAlgorithms
security property has been enhanced to support disabling TLS cipher suites using a wildcard syntax. This new syntax allows you to more easily disable more than one cipher suite. For example,TLS_RSA_*
would disable all cipher suites starting with “TLS_RSA_”. Only cipher suites starting with “TLS_” can be disabled using this mechanism.Issue: JDK-8341964
-
Entrust TLS Server Certificates Distrusted
The JDK will no longer trust TLS Server certificates issued by Entrust. The list of affected certificates includes certificates branded as Entrust and AffirmTrust, which was managed by Entrust. TLS Server certificates issued on or before November 11, 2024 will continue to be trusted until they expire. Certificates issued after that date will be rejected. See the release note for more information and a list of Certificate Authorities that are affected.
This change has already been made in Oracle’s JDK 23.0.1, 21.0.5, 17.0.13, 11.0.25, and 8u431 releases.
Issue: JDK-8337664
-
TLS_RSA Cipher Suites Disabled by Default
The TLS_RSA cipher suites are now disabled by default. These cipher suites do not preserve forward secrecy and RFC 9325 recommends that they should not be used. This change disables any cipher suite starting with “TLS_RSA_”.
Users can re-enable these cipher suites, at their own risk, by removing “TLS_RSA_*” from the
jdk.tls.disabledAlgorithms
security property in thejava.security
configuration file.Issue: JDK-8245545
Security Manager
-
Permanently Disable the Security Manager
In JDK 17, the Security Manager was deprecated for removal via JEP 411. This included the
java.lang.SecurityManager
API and several APIs related to the Security Manager.In this release, we have taken the next major step and permanently disabled the Security Manager. It is no longer possible to enable a Security Manager at startup on the command line, or at run time by calling
System.setSecurityManager
. The Security Manager related APIs have been degraded to be non-functional or to behave as in prior releases when a Security Manager was not enabled.Developers should take action to remove dependencies on the Security Manager, if applicable. There are several methods you can use to determine if your code is dependent on the Security Manager:
- Check scripts or documentation for Security Manager references
- Run the application on one of JDK 17 through 23 and look for deprecation warnings on the console
- Run the application on one of JDK 17 through 23 with the command-line
option
-Djava.security.manager=disallow
. If the code is dynamically setting a Security Manager, it will throw anUnsupportedOperationException
. - Use the
jdeprscan
tool on JDK 17 or later to scan for uses of deprecated Security Manager APIs
The JVM will exit with a fatal error at startup if an application is run with a Security Manager, ex:
java –Djava.security.manager MyApp Error occurred during initialization of VM java.lang.Error: A command line option has attempted to allow or enable the Security Manager. Enabling a Security Manager is not supported. at java.lang.System.initPhase3(java.base@24-internal/System.java:2067)
If an application enables a Security Manager at run time, an
UnsupportedOperationException
will be thrown, ex:
java MyApp Exception in thread "main" java.lang.UnsupportedOperationException: Setting a Security Manager is not supported at java.base/java.lang.System.setSecurityManager(System.java:320) ...
Libraries supporting the Security Manager typically use one or two common coding patterns, ex:
// checking permissions SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(...); } // asserting privileges SomeType v = AccessController.doPrivileged( (PrivilegedAction<SomeType>)() -> { ... return theResult; });
These methods will behave the same as in previous JDK releases when a Security Manager was not enabled:
System.getSecurityManager
will always returnnull
andAccessController.doPrivileged
will execute the action immediately.A small number of applications or libraries use advanced parts of the Security Manager APIs, ex:
AccessController::checkPermission
to check permissions directly, orPolicy::setPolicy
to use a custom policy implementation.These APIs, among others, have been degraded to throw exceptions or provide an execution environment that disallows access to all resources by default.
For applications that use JAAS,
Subject.getSubject
has been changed to always throwUnsupportedOperationException
. This API depends on the terminally deprecatedAccessControlContext
API. Replacement APIs were added in JDK 18. If using this API, you must replace calls toSubject.getSubject
withSubject.current
and you should replace calls toSubject.doAs
withSubject.callAs
.See the CSR for a complete list of API changes.
In a future release the Security Manager APIs will be removed.
Miscellaneous
-
Support for Including Security Properties Files
The
java.security
security properties file now supports including other properties files. A newinclude <file>
directive can be added to include another properties file. The effect of including a file is equivalent to defining its properties inline at the inclusion point. This feature is very useful for defining different property files that can be included based on different security profiles.For more information and examples, see the Security Properties Files Inclusion section of the Security Developer Guide.
Issue: JDK-8319332